﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Data.OleDb;
using System.Data;

namespace GlobalTracker.WebService.Core
{
  /// <summary>
  /// Esta classe é responsável por estabelcer uma conexão com o Banco de Dados SQL Server e
  /// executar query que retorne consultas feitas a uma tabela, bem como realize inserção, atualização(update)
  /// e excusão de dados. A mesma tabém oferece suporte a alteração de estrutura de tabelas.
  /// 
  /// Ela foi criada para satisfazer diretamente os casos de uso:
  /// - W10: Interagir com Banco de Dados da Web
  /// - M11: Interagir com Banco de Dados da Web
  /// </summary>
  public class DatabaseAccess
  {
    // Objeto para estabelecer conexão com o banco de dados Microsoft SQL Server.
    private System.Data.SqlClient.SqlConnection connection;

    /// <summary>
    /// Construtor.
    /// </summary>
    public DatabaseAccess()
    {
    }

    /// <summary>
    /// Método responsável por realizar a conexão com o banco de dados.
    /// </summary>
    /// <returns>true = Conectou / false = Erro de Conexão</returns>
    public bool Connect()
    {
      // Recupera a string de conexão que contém os parametros para estabelece conexão com o banco de dados.
      // A definição da mesma encontra-se no arquivo Web.Config deste Web Service.
      string strConnection = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;

      // Instancia e abre conexão.          
      try
      {
        connection = new System.Data.SqlClient.SqlConnection(strConnection);
        connection.Open();
        return true;
      }
      catch (Exception exp)
      {
        connection.Dispose();
        throw exp;
      }
    }

    /// <summary>
    /// Método responsável por realizar um teste de conexão com o banco de dados.
    /// </summary>
    /// <returns>true = Conectou / false = Erro de Conexão</returns>
    public string ConnectTest()
    {
      //// Recupera a string de conexão que contém os parametros para estabelece conexão com o banco de dados.
      // A definição da mesma encontra-se no arquivo Web.Config deste Web Service.
      string strConnection = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; //System.Configuration.ConfigurationManager.AppSettings["ConnectionString"].ToLower();

      // Instancia e abre conexão.          
      try
      {
        connection = new System.Data.SqlClient.SqlConnection(strConnection);
        connection.Open();
        return "ok"; // Se conectou sem erros retorna a string "ok".
      }
      catch (Exception exp)
      {
        connection.Dispose();
        return exp.Message; // Se houve erros retorna uma string com a mensagem de erro.
      }
    }

    /// <summary>
    /// Método responsável por realizar a desconexão do banco de dados.
    /// </summary>
    /// <returns>true = Desconectou / false = Não conseguiu desconectar</returns>
    public bool Disconnect()
    {
      // Fecha e libera objeto de conexão.          
      try
      {
        connection.Close();
        connection.Dispose();
        return true;
      }
      catch (Exception exp) // Recupera exceção.
      {
        connection.Dispose();
        throw exp; // Levanta a exceção apresentada.
      }
    }

    /// <summary>
    /// Método responsável por carregar e retornar um DataSet com a consulta passada.
    /// </summary>
    /// <param name="comand">Comando SQL</param>
    /// <returns>DataSet com o resultado do comando SQL. Retorna null se ocorreu erro.</returns>
    public DataSet GetDataSet(string command)
    {
      // Verifica se foi passado um comando.
      if (command.Trim().Length == 0) 
        return null; // Retorna nulo caso não tenha sido passado um comando.

      // Instancia um objeto do tipo DataSet, que irá receber os resultados da query executada.
      DataSet dataSet = new DataSet(); 

      try
      {
        // Instancia um Data Adapter, que será utilizado para preencher o DataSet.
        IDbDataAdapter dataAdapter = new System.Data.SqlClient.SqlDataAdapter(); 
        this.Connect(); // Conecta ao banco de dados.

        if (connection != null) // Se o objeto de conexão não for nulo.
        {
          // Atribui query que será executada ao Data Adapter.
          dataAdapter.SelectCommand = new System.Data.SqlClient.SqlCommand(command, connection); 
          // Preenche o DataSet com o resultado da query.
          dataAdapter.Fill(dataSet);
          // Desconecta do banco de dados.
          this.Disconnect();
        }
      }
      catch
      {
        // Libera o DataSet caso tenha ocorrido algum erro na execução e desconecta do banco de dados.
        dataSet = null;
        this.Disconnect();
      }

      // Retorna o resultado de execução da query ou nulo caso tenha ocorrido algum erro.
      return dataSet;
    }

    /// <summary>
    /// Método responsável por executar uma query de Insert, Delete ou Update.
    /// </summary>
    /// <param name="command">Comando SQL</param>
    /// <returns>Retorna uma string com a quantidade de registros afetados ou "Error" caso tenha ocorrido erro.</returns>   
    public string ExecuteCommand(string command)
    {
      // Verifica se foi passado um comando.
      if (command.Trim().Length == 0)
        return string.Empty;  // Retorna uma string vazia caso não tenha sido passado um comando.

      // Declara objeto que será utilizado para executar uma query DML.
      System.Data.SqlClient.SqlCommand sqlCommand = null;

      try
      {
        this.Connect(); // Conecta ao banco de dados.
        if (connection != null) // Se o objeto de conexão não for nulo.
        {
          // Atribui query ao SqlCommand.
          sqlCommand = new System.Data.SqlClient.SqlCommand(command, connection);
          // Retorna resultado da execução do comando.
          string resultado = sqlCommand.ExecuteNonQuery().ToString();
          // Libera SqlCommand.
          sqlCommand.Dispose();
          // Desconecta do banco de dados.
          this.Disconnect();
          // Retorna resuldado.
          return resultado;
        }
        else
        {
          return "Não existe conexão com o banco de dados.";
        }
      }
      catch (Exception exp)
      {
        // Libera SqlCommand.
        sqlCommand.Dispose();
        // Deconecta do banco de dados.
        this.Disconnect();
        // Retorna mensagem de erro durante o processo de execução da query.
        return "Erro: \r\n" + exp.Message.ToString();
      }
    }

    /// <summary>
    /// Método responsável por retornar a primeira coluna da primeira linha da consulta, indeal para consultas rápidas como count, sum, etc...
    /// </summary>
    /// <param name="command">Comando SQL</param>
    /// <returns>Valor retornado pela consulta ou "Erro" caso tenha ocorrido erro. </returns>
    public string GetDataToString(string command)
    {
      // Verifica se foi passado um comando.
      if (command.Trim().Length == 0)
        return null; // Retorna nulo caso não tenha sido passado um comando.

      // Instancia um objeto do tipo DataSet, que irá receber os resultados da query executada.
      DataSet dataSet = new DataSet();

      try
      {
        // Instancia um Data Adapter, que será utilizado para preencher o DataSet.
        IDbDataAdapter dataAdapter = new System.Data.SqlClient.SqlDataAdapter();
        this.Connect(); // Conecta ao banco de dados.

        if (connection != null) // Se o objeto de conexão não for nulo.
        {
          // Atribui query que será executada ao Data Adapter.
          dataAdapter.SelectCommand = new System.Data.SqlClient.SqlCommand(command, connection);
          // Preenche o DataSet com o resultado da query.
          dataAdapter.Fill(dataSet);
          // Desconecta do banco de dados.
          this.Disconnect();
          // Se a execução da query retornou uma tabela com pelo menos uma linha...
          if ((dataSet.Tables.Count > 0) && (dataSet.Tables[0].Rows.Count > 0))
          {
            // ... retorna o valor da primeira coluna e primeira linha.
            return dataSet.Tables[0].Rows[0][0].ToString();
          }
          else
          {
            // ... retorna uma string vazia.
            return string.Empty;
          }
        }
        else
        {
          return string.Empty;
        }
      }
      catch
      {
        // Libera o DataSet caso tenha ocorrido algum erro na execução e desconecta do banco de dados.
        dataSet = null;
        this.Disconnect();
        return string.Empty;
      }    
    }

    /// <summary>
    /// Propriedade da classe que retorna conexão corrente.
    /// </summary>
    public System.Data.SqlClient.SqlConnection CurrentConnection
    {
      get
      {
        return connection;
      }
    }
  }
}